﻿using System;
using System.Collections.Generic;
using System.Reflection;

namespace GT
{
    public static partial class Extensions
    {
        public static Type GetCommonAncestor(this Type type, Type targetType)
        {
            if (targetType.IsAssignableFrom(type))
                return targetType;

            var baseType = targetType.BaseType;
            while (baseType != null && !baseType.IsPrimitive)
            {
                if (baseType.IsAssignableFrom(type))
                    return baseType;
                baseType = baseType.BaseType;
            }
            return null;
        }

        public static string GetDisplayName(this Type input)
        {
            string displayName = input.Name;

            for (int i = displayName.Length - 1; i >= 0; i--)
            {
                if (displayName[i] == char.ToUpper(displayName[i]))
                    if (i > 0)
                        displayName = displayName.Insert(i, " ");
            }
            return displayName;
        }

        public static IEnumerable<string> GetReferencesAssembliesPaths(this Type type)
        {
            yield return type.Assembly.Location;

            foreach (AssemblyName assemblyName in type.Assembly.GetReferencedAssemblies())
            {
                yield return Assembly.ReflectionOnlyLoad(assemblyName.FullName).Location;
            }
        }

        public static bool IsDerived<T>(this Type type)
        {
            Type baseType = typeof(T);

            if (baseType.FullName == type.FullName)
            {
                return true;
            }

            if (type.IsClass)
            {
                return baseType.IsClass
                    ? type.IsSubclassOf(baseType)
                    : baseType.IsInterface
                        ? type.IsImplemented(baseType)
                        : false;
            }
            else if (type.IsInterface && baseType.IsInterface)
            {
                return type.IsImplemented(baseType);
            }
            return false;
        }

        public static bool IsImplemented(this Type type, Type baseType)
        {
            Type[] faces = type.GetInterfaces();
            foreach (Type face in faces)
            {
                if (baseType.Name.Equals(face.Name))
                {
                    return true;
                }
            }
            return false;
        }
    }
}
